/*! \file list.h
	\author tsvetkov_ii

	Defines a list node
*/
#pragma once
#include "abstractnode.h"
#include "id.h"
#include "expr.h"
#include <vector>


template<
typename _nodeType
>
class ListNode: public AbstractNode
{
 private:
	     std::vector<_nodeType *> c_vector;
		 const char *             c_type_string;
 public:
	    ListNode(const char * tname): AbstractNode()
		{
			c_type_string= tname;
		}


		_nodeType * add(_nodeType * n)
		{ 
			c_vector.push_back(n); 
			return n;
		}

		_nodeType * push_front(_nodeType * n)
		{ 
			std::vector<_nodeType *>::iterator it;
			it = c_vector.begin();
			c_vector.insert(it,n);

			return n;
		}

		void write(GraphStream * s)
		{
			this->accept(s);

			fprintf(s->stream,"\tnode_%d [ label=\"ListNode<%s>\" shape=\"rectangle\"]\n",this->number(),c_type_string);
			for(unsigned int i=0;i<c_vector.size();i++) {
				c_vector[i]->write(s);
				fprintf(s->stream, "\tnode_%d -> node_%d\n",this->number(),c_vector[i]->number());
			}
		}

		~ListNode()
		{
			for (unsigned int i=0;i<c_vector.size();i++) {
				delete c_vector[i];
			}
		}
};


/*! \def CREATE_LIST(POS,TYPE)
    Creates a list node
*/
#define CREATE_LIST(TYPE) new ListNode<TYPE>(#TYPE)


class VarList: public AbstractNode
{
private:
	std::vector<Id *> c_names;

public:

	VarList(Id * name);

	void add(Id * name);

	void write(GraphStream * s);

	~VarList();

};

class MethodVarList : public AbstractNode
{
private:
	std::vector<Expression *> c_names;
	std::vector<Id *> c_params;

public:
	
	MethodVarList(Expression * name);

	MethodVarList(Expression * name, Id * param);

	void add(Expression * name, Id * param);

	void write(GraphStream * s);

	~MethodVarList();
};